/**************************************************************
*
* M3D_VMX_HELPERS.H
**************************************************************/

#ifndef _M3D_VMX_HELPERS_H_
#define _M3D_VMX_HELPERS_H_




#ifdef _AP_PC
   #define fpmax(a,b) ((a) > (b)) ? (a) : (b)
   #define fpmin(a,b) ((a) < (b)) ? (a) : (b)
#endif


#if defined _AP_PS3

#include <vec_types.h>
#ifdef SPU
#include <vmx2spu.h>
#else
#include <altivec.h>
#endif

#include <vectormath/cpp/vectormath_aos.h>


#if defined (SPU)
__INLINE float __fsel (float cmp, float a, float b)
{
   return si_to_float((qword)spu_sel(spu_splats(b), spu_splats(a), vec_cmpge(spu_splats(cmp), (vec_float4)(0.0f)) ) );
}
#endif



#ifdef SPU
   #define M3D_SUPPRESS_OPTIMIZATION

   #define fpmax(a,b) ((a) > (b)) ? (a) : (b)
   #define fpmin(a,b) ((a) < (b)) ? (a) : (b)

#else
   #include <ppu_intrinsics.h>

   #define fpmax(a,b) __fsel((a)-(b),a,b)
   #define fpmin(a,b) __fsel((a)-(b),b,a)
#endif


// PS3 AltiVec Helper functions.
// Mostly copied out of ppu/include/vecotrmath/c/vec_aos.h, but I couldn't get that
// file to #include properly; also, it has crappy naming conventions.
// Why does Sony make it so difficult?

#define _O_VECTORMATH_PERM_X 0x00010203
#define _O_VECTORMATH_PERM_Y 0x04050607
#define _O_VECTORMATH_PERM_Z 0x08090a0b
#define _O_VECTORMATH_PERM_W 0x0c0d0e0f
#define _O_VECTORMATH_PERM_A 0x10111213
#define _O_VECTORMATH_PERM_B 0x14151617
#define _O_VECTORMATH_PERM_C 0x18191a1b
#define _O_VECTORMATH_PERM_D 0x1c1d1e1f

#define _O_VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_B, _O_VECTORMATH_PERM_W, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_C, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_B })
#define _O_VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_W, _O_VECTORMATH_PERM_C, _O_VECTORMATH_PERM_D })
#define _O_VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_B, _O_VECTORMATH_PERM_X })     
#define _O_VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_C, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_C })
#define _O_VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_W, _O_VECTORMATH_PERM_Z })
#define _O_VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_B, _O_VECTORMATH_PERM_W, _O_VECTORMATH_PERM_D })
#define _O_VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_C, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_C, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y })
#define _O_VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_C, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_C })
#define _O_VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_B, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_A })
#define _O_VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_B })
#define _O_VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_C })
#define _O_VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_B, _O_VECTORMATH_PERM_B, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_XYZA ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_A })
#define _O_VECTORMATH_PERM_ZXYW ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_W })
#define _O_VECTORMATH_PERM_YZXW ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_W })
#define _O_VECTORMATH_PERM_YZAB ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_B })
#define _O_VECTORMATH_PERM_ZABC ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_B, _O_VECTORMATH_PERM_C })
#define _O_VECTORMATH_PERM_XYAW ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_W })
#define _O_VECTORMATH_PERM_XAZW ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_W })
#define _O_VECTORMATH_PERM_YXXD ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_D })
#define _O_VECTORMATH_PERM_CXYX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_C, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_WXYZ ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_W, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_Z })
#define _O_VECTORMATH_PERM_XYZD ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_D })
#define _O_VECTORMATH_PERM_ZXBX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_X, _O_VECTORMATH_PERM_B, _O_VECTORMATH_PERM_X })
#define _O_VECTORMATH_PERM_YZAX ((vec_uchar16)(vec_uint4){ _O_VECTORMATH_PERM_Y, _O_VECTORMATH_PERM_Z, _O_VECTORMATH_PERM_A, _O_VECTORMATH_PERM_X })


#define _O_VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0x00000000, 0x00000000, 0x00000000 }
#define _O_VECTORMATH_MASK_0x0F00 (vec_uint4){ 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }
#define _O_VECTORMATH_MASK_0x00F0 (vec_uint4){ 0x00000000, 0x00000000, 0xffffffff, 0x00000000 }
#define _O_VECTORMATH_MASK_0x000F (vec_uint4){ 0x00000000, 0x00000000, 0x00000000, 0xffffffff }
#define _O_VECTORMATH_MASK_0xFFF0 (vec_uint4){ 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000 }



static inline void vec_store_unaligned(const vec_float4, float *, const unsigned int) __attribute__((always_inline));
static inline void vec_store_unaligned(const vec_float4 vec, float *v, const unsigned int offset = 0)
{
   vec_stvlx((vec_uchar16)vec, offset, (unsigned char*)v);
   vec_stvrx((vec_uchar16)vec, offset+16, (unsigned char*)v);
}

static inline void vec_store3_unaligned(const vec_float4, float *, const unsigned int) __attribute__((always_inline));
static inline void vec_store3_unaligned(const vec_float4 vec, float *v, const unsigned int offset = 0)
{
   vec_uchar16 p = vec_lvsr(offset, v);
   vec_float4 store = vec_perm(vec, vec, p);

   vec_ste(store, 0, v);
   vec_ste(store, 4, v);
   vec_ste(store, 8, v);
}



static inline vec_short8 vec_load_unaligned(const short *, const int) __attribute__((always_inline));
static inline vec_short8 vec_load_unaligned(const short *v, const int offset = 0)
{
   return vec_or(vec_lvlx(offset, (signed short*)v), vec_lvrx(offset+16, (signed short*)v));
}

static inline vec_float4 vec_load_unaligned(const float *, const unsigned int) __attribute__((always_inline));
static inline vec_float4 vec_load_unaligned(const float *v, const unsigned int offset = 0)
{
   return vec_or(vec_lvlx(offset, (float*)v), vec_lvrx(offset+16, (float*)v));
}

static inline vec_float4 vec_dot3(const vec_float4, const vec_float4) __attribute__((always_inline));
static inline vec_float4 vec_dot3(const vec_float4 vec0, const vec_float4 vec1)
{
   vec_float4 v30 = (vec_float4)vec_sel(_O_VECTORMATH_MASK_0xFFF0, (vec_uint4)vec0, _O_VECTORMATH_MASK_0xFFF0);
   vec_float4 v31 = (vec_float4)vec_sel(_O_VECTORMATH_MASK_0xFFF0, (vec_uint4)vec1, _O_VECTORMATH_MASK_0xFFF0);

   v30 = vec_madd(v30, v31, (vec_float4)(0.0f));
   v31 = vec_sld(v30, v30, 8);
   v30 = vec_add(v30, v31);
   v31 = vec_sld(v30, v30, 4);
   return vec_add(v30, v31);
}

static inline vec_float4 vec_dot4(const vec_float4, const vec_float4) __attribute__((always_inline));
static inline vec_float4 vec_dot4(const vec_float4 vec0, const vec_float4 vec1)
{
   vec_float4 v0 = vec_madd(vec0, vec1, (vec_float4)(0.0f));
   vec_float4 v1 = vec_sld(v0, v0, 8);
   v0 = vec_add(v0, v1);
   v1 = vec_sld(v0, v0, 4);
   return vec_add(v0, v1);
}

static inline vec_float4 vec_cross3(const vec_float4, const vec_float4) __attribute__((always_inline));
static inline vec_float4 vec_cross3(const vec_float4 vec0, const vec_float4 vec1)
{
    vec_float4 tmp0 = vec_perm(vec0, vec0, _O_VECTORMATH_PERM_YZXW);
    vec_float4 tmp1 = vec_perm(vec1, vec1, _O_VECTORMATH_PERM_ZXYW);
    vec_float4 tmp2 = vec_perm(vec0, vec0, _O_VECTORMATH_PERM_ZXYW);
    vec_float4 tmp3 = vec_perm(vec1, vec1, _O_VECTORMATH_PERM_YZXW);

    vec_float4 result;
    result = vec_madd(tmp0, tmp1, (vec_float4)(0.0f));
    result = vec_nmsub(tmp2, tmp3, result);

    return result;
}

static inline vec_float4 MxV(const vec_float4, const vec_float4,
							 const vec_float4, const vec_float4,
							 const vec_float4) __attribute__((always_inline));
static inline vec_float4 MxV(const vec_float4 a, const vec_float4 b,
							 const vec_float4 c, const vec_float4 d,
							 const vec_float4 v)
{
   vec_float4 zero = (vec_float4)(0.0f);
	vec_float4 xxxx = vec_splat(v, 0);
	vec_float4 yyyy = vec_splat(v, 1);
	vec_float4 zzzz = vec_splat(v, 2);
	vec_float4 wwww = vec_splat(v, 3);

	vec_float4 tmp0, tmp1;

   tmp0 = vec_madd(a, xxxx, zero);
	tmp1 = vec_madd(b, yyyy, zero);
	tmp0 = vec_madd(c, zzzz, tmp0);
	tmp1 = vec_madd(d, wwww, tmp1);
	return vec_add(tmp0, tmp1);
}




namespace Vectormath {

namespace Aos {


//
// A 4x4 matrix in array-of-structures format - row-vector convention 
//
class Matrix4R {
    Vector4 mRow0;
    Vector4 mRow1;
    Vector4 mRow2;
    Vector4 mRow3;

public:
             inline Matrix4R( ) { };
             inline Matrix4R( const Matrix4R & mat );
             inline Matrix4R( Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3 );
    explicit inline Matrix4R( float scalar );

    inline Matrix4R & operator =( const Matrix4R & mat );

    inline Matrix4R & setRow0( Vector4 row0 );
    inline Matrix4R & setRow1( Vector4 row1 );
    inline Matrix4R & setRow2( Vector4 row2 );
    inline Matrix4R & setRow3( Vector4 row3 );
    inline const Vector4 getRow0( ) const;
    inline const Vector4 getRow1( ) const;
    inline const Vector4 getRow2( ) const;
    inline const Vector4 getRow3( ) const;

    inline Matrix4R &    setRow( int row, Vector4 vec );
    inline const Vector4 getRow( int row ) const;

    inline Vector4 &     operator []( int row );
    inline const Vector4 operator []( int row ) const;

    inline Matrix4R &  setElem( int row, int col, float val );
    inline float getElem( int row, int col) const;
    
    inline const Matrix4R operator +( const Matrix4R & mat ) const;
    inline const Matrix4R operator -( const Matrix4R & mat ) const;
    inline const Matrix4R operator -( ) const;
    inline const Matrix4R operator *( float scalar ) const;
    inline const Vector4  operator *( Vector4 vec ) const;
    inline const Matrix4R operator *( const Matrix4R & mat ) const;

    inline Matrix4R & operator +=( const Matrix4R & mat );
    inline Matrix4R & operator -=( const Matrix4R & mat );
    inline Matrix4R & operator *=( float scalar );
    inline Matrix4R & operator *=( const Matrix4R & mat );

    static inline const Matrix4R identity( );

}
#ifndef SPU
__attribute__((d64_abi))
#endif
;

// Multiply a 4x4 matrix by a scalar
// 
inline const Matrix4R operator *( float scalar, const Matrix4R & mat );

// Transpose of a 4x4 matrix
// 
inline const Matrix4R transpose( const Matrix4R & mat );








inline Matrix4R::Matrix4R( const Matrix4R & mat )
{
    mRow0 = mat.mRow0;
    mRow1 = mat.mRow1;
    mRow2 = mat.mRow2;
    mRow3 = mat.mRow3;
}

inline Matrix4R::Matrix4R( float scalar )
{
    mRow0 = Vector4( scalar );
    mRow1 = Vector4( scalar );
    mRow2 = Vector4( scalar );
    mRow3 = Vector4( scalar );
}

inline Matrix4R::Matrix4R( Vector4 _row0, Vector4 _row1, Vector4 _row2, Vector4 _row3 )
{
    mRow0 = _row0;
    mRow1 = _row1;
    mRow2 = _row2;
    mRow3 = _row3;
}

inline Matrix4R & Matrix4R::setRow0( Vector4 _row0 )
{
    mRow0 = _row0;
    return *this;
}

inline Matrix4R & Matrix4R::setRow1( Vector4 _row1 )
{
    mRow1 = _row1;
    return *this;
}

inline Matrix4R & Matrix4R::setRow2( Vector4 _row2 )
{
    mRow2 = _row2;
    return *this;
}

inline Matrix4R & Matrix4R::setRow3( Vector4 _row3 )
{
    mRow3 = _row3;
    return *this;
}

inline Matrix4R & Matrix4R::setRow( int row, Vector4 vec )
{
    *(&mRow0 + row) = vec;
    return *this;
}

inline Matrix4R & Matrix4R::setElem( int row, int col, float val )
{
    (*this)[row].setElem(col, val);
    return *this;
}


inline float Matrix4R::getElem( int row, int col) const
{
    return this->getRow(row).getElem(col);
}

inline const Vector4 Matrix4R::getRow0( ) const
{
    return mRow0;
}

inline const Vector4 Matrix4R::getRow1( ) const
{
    return mRow1;
}

inline const Vector4 Matrix4R::getRow2( ) const
{
    return mRow2;
}

inline const Vector4 Matrix4R::getRow3( ) const
{
    return mRow3;
}

inline const Vector4 Matrix4R::getRow( int row ) const
{
    return *(&mRow0 + row);
}

inline Vector4 & Matrix4R::operator []( int row )
{
    return *(&mRow0 + row);
}

inline const Vector4 Matrix4R::operator []( int row ) const
{
    return *(&mRow0 + row);
}

inline Matrix4R & Matrix4R::operator =( const Matrix4R & mat )
{
    mRow0 = mat.mRow0;
    mRow1 = mat.mRow1;
    mRow2 = mat.mRow2;
    mRow3 = mat.mRow3;
    return *this;
}

inline const Matrix4R transpose( const Matrix4R & mat )
{
    vec_float4 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3;
    tmp0 = vec_mergeh( mat.getRow0().get128(), mat.getRow2().get128() );
    tmp1 = vec_mergeh( mat.getRow1().get128(), mat.getRow3().get128() );
    tmp2 = vec_mergel( mat.getRow0().get128(), mat.getRow2().get128() );
    tmp3 = vec_mergel( mat.getRow1().get128(), mat.getRow3().get128() );
    res0 = vec_mergeh( tmp0, tmp1 );
    res1 = vec_mergel( tmp0, tmp1 );
    res2 = vec_mergeh( tmp2, tmp3 );
    res3 = vec_mergel( tmp2, tmp3 );
    return Matrix4R(
        Vector4( res0 ),
        Vector4( res1 ),
        Vector4( res2 ),
        Vector4( res3 )
    );
}


inline const Matrix4R Matrix4R::operator +( const Matrix4R & mat ) const
{
    return Matrix4R(
        ( mRow0 + mat.mRow0 ),
        ( mRow1 + mat.mRow1 ),
        ( mRow2 + mat.mRow2 ),
        ( mRow3 + mat.mRow3 )
    );
}

inline const Matrix4R Matrix4R::operator -( const Matrix4R & mat ) const
{
    return Matrix4R(
        ( mRow0 - mat.mRow0 ),
        ( mRow1 - mat.mRow1 ),
        ( mRow2 - mat.mRow2 ),
        ( mRow3 - mat.mRow3 )
    );
}

inline Matrix4R & Matrix4R::operator +=( const Matrix4R & mat )
{
    *this = *this + mat;
    return *this;
}

inline Matrix4R & Matrix4R::operator -=( const Matrix4R & mat )
{
    *this = *this - mat;
    return *this;
}

inline const Matrix4R Matrix4R::operator -( ) const
{
    return Matrix4R(
        ( -mRow0 ),
        ( -mRow1 ),
        ( -mRow2 ),
        ( -mRow3 )
    );
}

inline const Matrix4R Matrix4R::operator *( float scalar ) const
{
   Vector4 _scalar(vec_splats(scalar));
    return Matrix4R(
        mulPerElem(mRow0, _scalar),
        mulPerElem(mRow1, _scalar),
        mulPerElem(mRow2, _scalar),
        mulPerElem(mRow3, _scalar)
    );
}

inline Matrix4R & Matrix4R::operator *=( float scalar )
{
    return *this *= scalar;
}

inline const Matrix4R operator *( float scalar, const Matrix4R & mat )
{
    return scalar * mat;
}

inline const Vector4 Matrix4R::operator *( Vector4 vec ) const
{
    vec_float4 tmp0, tmp1, res;
    vec_float4 xxxx, yyyy, zzzz, wwww;
    vec_float4 zero = (vec_float4)(0.0f);
    xxxx = vec_splat( vec.get128(), 0 );
    yyyy = vec_splat( vec.get128(), 1 );
    zzzz = vec_splat( vec.get128(), 2 );
    wwww = vec_splat( vec.get128(), 3 );
    tmp0 = vec_madd( mRow0.get128(), xxxx, zero );
    tmp1 = vec_madd( mRow1.get128(), yyyy, zero );
    tmp0 = vec_madd( mRow2.get128(), zzzz, tmp0 );
    tmp1 = vec_madd( mRow3.get128(), wwww, tmp1 );
    res = vec_add( tmp0, tmp1 );
    return Vector4( res );
}

inline const Matrix4R Matrix4R::operator *( const Matrix4R & mat ) const
{
    return Matrix4R(
        ( mat * mRow0 ),
        ( mat * mRow1 ),
        ( mat * mRow2 ),
        ( mat * mRow3 )
    );
}

inline Matrix4R & Matrix4R::operator *=( const Matrix4R & mat )
{
    *this = *this * mat;
    return *this;
}

inline const Matrix4R Matrix4R::identity( )
{
    return Matrix4R(
        Vector4::xAxis( ),
        Vector4::yAxis( ),
        Vector4::zAxis( ),
        Vector4::wAxis( )
    );
}

} // namespace Aos
} // namespace Vectormath



#endif //_AP_PS3

#endif // _M3D_VMX_HELPERS_H_

//
// End-of-file M3D_VMX_HELPERS.H
//

